import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
import { MessageTip } from '@app-cad/common/utils/MessageTip';
import { useClickAway } from 'ahooks';
import { Button, Input, Spin, Tooltip, Tree, Modal } from 'antd';
import type { DataNode } from 'antd/es/tree';
import { isEmpty } from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
  DeleteSvgComponent,
  NewCustomMaterialSvgComponent,
  NewMaterialCategorySvgComponent,
  NewMaterialLibrarySvgComponent,
} from '../../icons';
import MenuPortal from './MenuPortal';
import TextInputModal from './TextInputModal';
import {
  getTreeByFactory,
  filterTree,
  getMenuItems,
  getNodeTypeMark,
  MaterialNodeType,
} from './utils';
import { materialHttpApi } from '@app-base/server/material-http';
const { Search } = Input;

type MaterialTreeProps<T> = {
  selectNode: T;
  setSelectNode: (node: T) => void;
  searchValue: string;
  setSearchValue: (val: string) => void;
  treeUpdateKey: number;
};

const MaterialTree: React.FC<MaterialTreeProps<CmdMaterialSpace.TreeNode>> = ({
  searchValue,
  setSelectNode,
  selectNode,
  setSearchValue,
  treeUpdateKey,
}) => {
  const [remoteTreeData, setRemoteTreeData] = useState<
    CmdMaterialSpace.TreeNode[]
  >([]);
  const [expandedKeys, setExpandedKeys] = useState<string[]>(['-1']);
  const [menu, setMenu] = useState<{
    visible: boolean;
    x: number;
    y: number;
    node: CmdMaterialSpace.TreeNode;
    type: string;
  } | null>(null);
  const menuRef = useRef(null);
  // 只保留一个通用文本输入弹窗
  const [textInputModal, setTextInputModal] = useState<{
    open: boolean;
    config: {
      title: string;
      label: string;
      placeholder: string;
      validateMessage: string;
      onOk: (name: string) => void;
    } | null;
    loading?: boolean;
    initialValue?: string;
  }>({ open: false, config: null, loading: false, initialValue: '' });
  const [curMenuNode, setCurMenuNode] = useState<CmdMaterialSpace.TreeNode>();
  const [copiedNode, setCopiedNode] = useState<CmdMaterialSpace.TreeNode>();
  const [treeLoading, setTreeLoading] = useState(false);

  useClickAway(() => {
    if (menu?.visible) setMenu(null);
  }, menuRef);

  const handleRightClick = ({ event, node }) => {
    const type = node.typeMark;
    if (['fav-root', 'lib-root', 'lib-category'].includes(type)) return;
    setMenu({
      visible: true,
      x: event.clientX + window.scrollX,
      y: event.clientY + window.scrollY,
      node,
      type,
    });
  };
  const handleMenuClick = (
    menuCmdKey: string,
    node: DataNode & CmdMaterialSpace.TreeNode,
  ) => {
    setExpandedKeys((prev) => {
      if (prev.includes(node.key as string)) return prev;
      return [...prev, node.key as string];
    });
    setSelectNode(node);
    setCurMenuNode(node);
    setMenu(null);
    switch (menuCmdKey) {
      case 'fav':
        favMatToCollection(node.key as string);
        break;
      case 'unfav':
        unFavMatToCollection(node.key as string, node.name);
        break;
      case 'new-cat':
        setTextInputModal({
          open: true,
          config: {
            title: '新建材料分类',
            label: '分类名称',
            placeholder: '请输入分类名称',
            validateMessage: '请输入分类名称',
            onOk: (name) => handleCreateCategory(name, node.id),
          },
          loading: false,
          initialValue: '',
        });
        break;
      case 'rename':
        setTextInputModal({
          open: true,
          config: {
            title: '重命名',
            label: '新名称',
            placeholder: '请输入新名称',
            validateMessage: '请输入新名称',
            onOk: (name) => handleRename(name, node),
          },
          loading: false,
          initialValue: node.name,
        });
        break;
      case 'delete':
        onDelete(node);
        break;
      case 'copy':
        setCopiedNode(node);
        break;
      case 'paste':
        onPaste(node);
        break;
      case 'new-mat':
        setTextInputModal({
          open: true,
          config: {
            title: '新建材料',
            label: '新名称',
            placeholder: '请输入新名称',
            validateMessage: '请输入新名称',
            onOk: (name) => newMaterial2Cat(name, node),
          },
          loading: false,
        });
        break;
    }
  };

  useEffect(() => {
    QueryTree();
  }, [treeUpdateKey]);

  const QueryTree = async () => {
    setTreeLoading(true);
    try {
      const res = await materialHttpApi.getMaterialLibrary();
      const data: CmdMaterialSpace.TreeNode[] = res.data || [];
      setRemoteTreeData(data);
      setTreeLoading(false);
    } catch {
      setTreeLoading(false);
    }
  };

  // 收藏材料
  const favMatToCollection = async (materialId: string) => {
    await materialHttpApi.favMaterial({ materialId });
    QueryTree();
  };
  // 取消收藏材料
  const unFavMatToCollection = (id: string, name?: string) => {
    Modal.confirm({
      title: `取消收藏`,
      content: `${name}，再次确认是否取消？`,
      okText: '确定',
      cancelText: '取消',
      onOk: async () => {
        await materialHttpApi.unFavMaterial({ id });
        QueryTree();
      },
    });
  };

  const exactTreeComputer: React.SetStateAction<DataNode[]> = useMemo(() => {
    const extraTree = getTreeByFactory(remoteTreeData, {
      unFavMatToCollection,
      favMatToCollection,
      selectNode: selectNode || ({} as CmdMaterialSpace.TreeNode),
    });
    return filterTree(extraTree, searchValue);
  }, [remoteTreeData, searchValue, selectNode]);

  // 新建材料库
  const handleCreateLibrary = async (name: string) => {
    setTextInputModal((prev) => ({ ...prev, loading: true }));
    try {
      await materialHttpApi.addMaterialLibrary({ libraryName: name });
      MessageTip.success('新建材料库成功');
      setTextInputModal({ open: false, config: null, loading: false });
      QueryTree();
    } catch (e) {
      setTextInputModal((prev) => ({ ...prev, loading: false }));
    }
  };
  // 新建材料分类
  const handleCreateCategory = async (
    name: string,
    materialCollectionId?: string,
  ) => {
    setTextInputModal((prev) => ({ ...prev, loading: true }));
    const libId = materialCollectionId ?? curMenuNode?.id;

    try {
      await materialHttpApi.addMaterialCategory({
        name,
        materialCollectionId: libId,
      });
      MessageTip.success('新建材料分类成功');
      setTextInputModal({ open: false, config: null, loading: false });
      QueryTree();
    } catch (e) {
      setTextInputModal((prev) => ({ ...prev, loading: false }));
    }
  };
  // 重命名材料库/分类/材料
  const handleRename = async (
    name: string,
    node: CmdMaterialSpace.TreeNode,
  ) => {
    setTextInputModal((prev) => ({ ...prev, loading: true }));
    try {
      const nodeType = getNodeTypeMark(node);
      if (nodeType === MaterialNodeType.CustomLib) {
        await materialHttpApi.renameMaterialLibrary({ id: node.id, name });
      }
      if (nodeType === MaterialNodeType.CustomCat) {
        await materialHttpApi.renameMaterialCategory({ id: node.id, name });
      }
      if (nodeType === MaterialNodeType.CustomMat) {
        await materialHttpApi.renameMaterial({ id: node.id, name });
      }
      MessageTip.success('重命名成功');
      setTextInputModal({
        open: false,
        config: null,
        loading: false,
        initialValue: '',
      });
      QueryTree();
    } catch (e) {
      setTextInputModal((prev) => ({ ...prev, loading: false }));
    }
  };

  // 新建材料
  const newMaterial2Cat = async (
    name: string,
    node: CmdMaterialSpace.TreeNode,
  ) => {
    await materialHttpApi.newMaterial2Cat({ materialTypeId: node.id, name });
    MessageTip.success('新建成功');
    setTextInputModal({
      open: false,
      config: null,
      loading: false,
      initialValue: '',
    });
    QueryTree();
  };

  const onDelete = (node: CmdMaterialSpace.TreeNode) => {
    Modal.confirm({
      title: `删除 ${node.name}`,
      content: '正在删除对象，再次确认是否删除？',
      okText: '确定',
      cancelText: '取消',
      onOk: async () => {
        try {
          const nodeType = getNodeTypeMark(node);
          const delActions = {
            [MaterialNodeType.CustomLib]: () =>
              materialHttpApi.delMaterialLib({ id: node.id }),
            [MaterialNodeType.CustomCat]: () =>
              materialHttpApi.delMaterialCat({ id: node.id }),
            [MaterialNodeType.CustomMat]: () =>
              materialHttpApi.delMaterial({ id: node.id }),
          };
          const deleteAction = delActions[nodeType];
          if (deleteAction) {
            await deleteAction();
            QueryTree();
            MessageTip.success('删除成功');
            if (selectNode.id === node.id) {
              setSelectNode(undefined);
            }
          } else {
            console.warn(`未知节点类型: ${nodeType}`);
          }
        } catch (error) {
          console.error('删除失败:', error);
        }
      },
    });
  };

  const onPaste = async (node: CmdMaterialSpace.TreeNode) => {
    if (isEmpty(copiedNode)) {
      MessageTip.error('请先复制');
    }
    await materialHttpApi.pasteMaterial2Cat({
      materialTypeId: node.id,
      materialId: copiedNode.id,
    });
    MessageTip.success('粘贴成功');
    QueryTree();
  };

  return (
    <div>
      <div
        className='border-r border-gray-200 p-2 pr-1 min-w-[260px] max-w-[300px] h-[560px] flex flex-col relative'
        onClick={() => setMenu(null)}
      >
        <Search
          placeholder='搜索项目'
          allowClear
          className='mb-3'
          value={searchValue}
          onChange={(e) => setSearchValue(e.target.value)}
        />
        <div className='flex-1 overflow-auto'>
          <Spin spinning={treeLoading}>
            <Tree
              treeData={exactTreeComputer}
              expandedKeys={expandedKeys}
              onExpand={(keys) => setExpandedKeys(keys as string[])}
              selectedKeys={[selectNode?.id]}
              onSelect={(_, { node }) => {
                setSelectNode(node as unknown as CmdMaterialSpace.TreeNode);
                setExpandedKeys((prev) => {
                  if (prev.includes(node.key as string)) return prev;
                  return [...prev, node.key as string];
                });
              }}
              showLine
              showIcon
              blockNode
              onRightClick={handleRightClick}
              switcherIcon={({ expanded }) =>
                expanded ? <MinusOutlined /> : <PlusOutlined />
              }
            />
          </Spin>
          <MenuPortal
            menu={menu}
            menuRef={menuRef}
            getMenuItems={(key, node) =>
              getMenuItems(key as MaterialNodeType, node)
            }
            handleMenuClick={handleMenuClick}
          />
        </div>
      </div>
      <div className='flex gap-3 mt-3 mb-1'>
        <Tooltip title='新建材料库'>
          <Button
            icon={<NewMaterialLibrarySvgComponent />}
            size='small'
            onClick={() => {
              setTextInputModal({
                open: true,
                config: {
                  title: '新建材料库',
                  label: '材料库名称',
                  placeholder: '请输入材料库名称',
                  validateMessage: '请输入材料库名称',
                  onOk: handleCreateLibrary,
                },
                loading: false,
              });
            }}
          />
        </Tooltip>
        <Tooltip title='新建材料分类'>
          <Button
            icon={<NewMaterialCategorySvgComponent />}
            size='small'
            disabled={
              !(getNodeTypeMark(selectNode) === MaterialNodeType.CustomLib)
            }
            onClick={() =>
              setTextInputModal({
                open: true,
                config: {
                  title: '新建材料分类',
                  label: '分类名称',
                  placeholder: '请输入分类名称',
                  validateMessage: '请输入分类名称',
                  onOk: (name) => handleCreateCategory(name, selectNode.id),
                },
                loading: false,
              })
            }
          />
        </Tooltip>
        <Tooltip title='新建自定义材料'>
          <Button
            icon={<NewCustomMaterialSvgComponent />}
            size='small'
            disabled={
              !(getNodeTypeMark(selectNode) === MaterialNodeType.CustomCat)
            }
            onClick={() =>
              setTextInputModal({
                open: true,
                config: {
                  title: '新建自定义材料',
                  label: '材料名称',
                  placeholder: '请输入材料名称',
                  validateMessage: '请输入材料名称',
                  onOk: (name) => newMaterial2Cat(name, selectNode),
                },
                loading: false,
              })
            }
          />
        </Tooltip>
        <Tooltip title='删除'>
          <Button
            icon={<DeleteSvgComponent />}
            size='small'
            onClick={() => onDelete(selectNode)}
            disabled={
              !selectNode ||
              [
                MaterialNodeType.StandardMaterial,
                MaterialNodeType.FavRoot,
                MaterialNodeType.StandardLibRoot,
                MaterialNodeType.StandardMaterialCategory,
              ].includes(selectNode.typeMark as MaterialNodeType)
            }
          />
        </Tooltip>
      </div>
      <TextInputModal
        open={textInputModal.open}
        loading={textInputModal.loading}
        onOk={textInputModal.config?.onOk}
        onCancel={() =>
          setTextInputModal({
            open: false,
            config: null,
            loading: false,
            initialValue: '',
          })
        }
        title={textInputModal.config?.title}
        label={textInputModal.config?.label}
        placeholder={textInputModal.config?.placeholder}
        validateMessage={textInputModal.config?.validateMessage}
        initialValue={textInputModal.initialValue}
      />
    </div>
  );
};

export default MaterialTree;
